﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Controls.Primitives;
using HelixToolkit;
using System.Windows.Media.Media3D;
using System.Windows.Input;
using Utils.EventAggregator;
using Microsoft.Practices.ServiceLocation;
using WPFColorPickerLib;
using System.Windows.Media;
using GameStudio.IDE.Common.Events.Graphics_Designer;

namespace GraphicsDesigner.Controls
{
    [TemplatePart(Name = "view1", Type = typeof(HelixView3D))]
    [TemplatePart(Name = "btnSave", Type = typeof(ButtonBase))]
    [TemplatePart(Name = "btnLoad", Type = typeof(ButtonBase))]
    [TemplatePart(Name = "btnClear", Type = typeof(ButtonBase))]
    [TemplatePart(Name = "btnChangeColor", Type = typeof(ButtonBase))]

   public class DesignerControl : Control
   {
        #region Private Members
       
        ButtonBase btnSave;
        ButtonBase btnLoad;
        ButtonBase btnClear;
        ButtonBase btnChangeColor;
        HelixView3D view1;

        private readonly MainViewModel vm = new MainViewModel();
        private string modelName;
        private string modelPath;

       #endregion

        #region Constructor
        
        public DesignerControl(string modelName, string modelPath)
        {
            this.modelName = modelName;
            this.modelPath = modelPath;
            vm.CurrentColor = Colors.BurlyWood;

            var eventAggregator = ServiceLocator.Current.GetInstance<IEventAggregator>();
            eventAggregator.GetEvent<ClearEvent>().Subscribe(OnClear);
            eventAggregator.GetEvent<ChangeColorEvent>().Subscribe(OnChangeColor);
            eventAggregator.GetEvent<SaveModelEvent>().Subscribe(OnSave);
            eventAggregator.GetEvent<LoadModelEvent>().Subscribe(OnLoad);
            eventAggregator.GetEvent<AddTextureEvent>().Subscribe(OnAddTexture);
            eventAggregator.GetEvent<AddCubeEvent>().Subscribe(OnAddCube);
            eventAggregator.GetEvent<AddSphereEvent>().Subscribe(OnAddSphere);
        }

        #endregion

        #region Public Methods
        
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            DataContext = vm;

            view1 = (HelixView3D)GetTemplateChild("view1");

            btnChangeColor = (ButtonBase)GetTemplateChild("btnChangeColor");
            //btnChangeColor.Click += new RoutedEventHandler(btnChangeColor_Click);

            btnSave = (ButtonBase)GetTemplateChild("btnSave");
            //btnSave.Click += new RoutedEventHandler(btnSave_Click);

            btnLoad = (ButtonBase)GetTemplateChild("btnLoad");
            //btnLoad.Click += new RoutedEventHandler(btnLoad_Click);

            btnClear = (ButtonBase)GetTemplateChild("btnClear");

            view1.MouseDown += new System.Windows.Input.MouseButtonEventHandler(view1_MouseDown);
            view1.MouseMove += new System.Windows.Input.MouseEventHandler(view1_MouseMove);

            view1.Focus();
        }

        #endregion

        #region Private Methods

        #region Event Handlers

        void OnChangeColor(string str)
        {
            ColorDialog colorDialog = new ColorDialog();
            SolidColorBrush myColor = new SolidColorBrush();
            if ((bool)colorDialog.ShowDialog())
            {
                myColor = new SolidColorBrush(colorDialog.SelectedColor);
            }
            
            //vm.PaletteIndex++;
            //vm.CurrentColor = vm.GetPaletteColor();
            vm.CurrentColor = myColor.Color;
            vm.Texture = null;
        }

        void OnClear(string str)
        {
            vm.Clear();
        }

        void OnLoad(string str)
        {
            // Configure open file dialog box
            Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
            dlg.FileName = "Model"; // Default file name
            dlg.DefaultExt = ".txt"; // Default file extension
            dlg.Filter = "Text documents (.txt)|*.txt"; // Filter files by extension

            // Show open file dialog box
            Nullable<bool> result = dlg.ShowDialog();

            // Process open file dialog box results
            if (result == true)
            {
                // Open document
                string fileName = dlg.FileName;
                vm.TryLoad(fileName);
            }
        }

        void OnSave(string str)
        {
            // Configure save file dialog box
            Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
            dlg.FileName = "Document"; // Default file name
            dlg.DefaultExt = ".text"; // Default file extension
            dlg.Filter = "Text documents (.txt)|*.txt"; // Filter files by extension

            // Show save file dialog box
            Nullable<bool> result = dlg.ShowDialog();

            // Process save file dialog box results
            if (result == true)
            {
                // Save document
                string filename = dlg.FileName;
                vm.Save(filename);
            }


        }

        void OnAddTexture(string str)
        {
            // Configure open file dialog box
            Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
            dlg.FileName = "Texture"; // Default file name
            //dlg.DefaultExt = ".png"; // Default file extension
            //dlg.Filter = "Text documents (.txt)|*.txt"; // Filter files by extension

            // Show open file dialog box
            Nullable<bool> result = dlg.ShowDialog();

            // Process open file dialog box results
            if (result == true)
            {
                // Open document
                string fileName = dlg.FileName;
                vm.Texture = fileName;
            }
        }

        void OnAddCube(string str)
        {
            vm.TypeOfShape = "cube";
        }

        void OnAddSphere(string str)
        {
            vm.TypeOfShape = "sphere";
        }
        void view1_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
        {
            UpdatePreview();
        }

        void view1_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            bool shift = (Keyboard.IsKeyDown(Key.LeftShift));
            var p = e.GetPosition(view1);

            Vector3D n;
            var source = FindSource(p, out n);
            if (source != null)
            {
                if (shift)
                    vm.Remove(source);
                else
                    vm.Add(source, n);
            }
            else
            {
                var ray = Viewport3DHelper.Point2DtoRay3D(view1.Viewport, p);
                if (ray != null)
                {
                    var pi = ray.PlaneIntersection(new Point3D(0, 0, 0.5), new Vector3D(0, 0, 1));
                    if (pi.HasValue)
                    {
                        var pRound = new Point3D(Math.Round(pi.Value.X), Math.Round(pi.Value.Y), 0);
                        //    var pRound = new Point3D(Math.Floor(pi.Value.X), Math.Floor(pi.Value.Y), Math.Floor(pi.Value.Z));
                        //var pRound = new Point3D((int)pi.Value.X, (int)pi.Value.Y, (int)pi.Value.Z);
                        vm.AddVoxel(pRound);
                    }
                }
            }
            vm.Save(modelPath + ".xml");
            UpdatePreview();
        }

        #endregion

        Model3D FindSource(Point p, out Vector3D normal)
        {
            var hits = Viewport3DHelper.FindHits(view1.Viewport, p);

            foreach (var h in hits)
            {
                if (h.Model == vm.PreviewModel)
                    continue;
                normal = h.Normal;
                return h.Model;
            }
            normal = new Vector3D();
            return null;
        }

        void UpdatePreview()
        {
            var p = Mouse.GetPosition(view1);
            bool shift = (Keyboard.IsKeyDown(Key.LeftShift));
            Vector3D n;
            var source = FindSource(p, out n);
            if (shift)
            {
                vm.PreviewVoxel(null);
                vm.HighlightVoxel(source);
            }
            else
            {
                vm.PreviewVoxel(source, n);
                vm.HighlightVoxel(null);
            }


        }

        #endregion
   }
}
